﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using System.Windows.Media.Imaging;

namespace ChessOnline
{
    public class GameDrawer
    {


        /// <summary>
        /// Canvas to process all requests for user. Must be 480x480 px.
        /// </summary>
        Canvas canvas = new Canvas();
        Dictionary<ChessOnlineService.ChessType, BitmapImage> chessImages = 
            new Dictionary<ChessOnlineService.ChessType, BitmapImage>();

        public GameDrawer()
        {
            // сопоставим фигуры с их изображением
            // черные
            chessImages.Add(ChessOnlineService.ChessType.BlackKing,
                new BitmapImage(new Uri("/ChessOnline;component/Images/black_king.png", UriKind.Relative)));
            chessImages.Add(ChessOnlineService.ChessType.BlackQueen,
                new BitmapImage(new Uri("/ChessOnline;component/Images/black_queen.png", UriKind.Relative)));
            chessImages.Add(ChessOnlineService.ChessType.BlackKnight,
                new BitmapImage(new Uri("/ChessOnline;component/Images/black_knight.png", UriKind.Relative)));
            chessImages.Add(ChessOnlineService.ChessType.BlackBishop,
                new BitmapImage(new Uri("/ChessOnline;component/Images/black_bishop.png", UriKind.Relative)));
            chessImages.Add(ChessOnlineService.ChessType.BlackRook,
                new BitmapImage(new Uri("/ChessOnline;component/Images/black_rook.png", UriKind.Relative)));
            chessImages.Add(ChessOnlineService.ChessType.BlackPawn,
                new BitmapImage(new Uri("/ChessOnline;component/Images/black_pawn.png", UriKind.Relative)));

            // белые
            chessImages.Add(ChessOnlineService.ChessType.WhiteKing,
                new BitmapImage(new Uri("/ChessOnline;component/Images/white_king.png", UriKind.Relative)));
            chessImages.Add(ChessOnlineService.ChessType.WhiteQueen,
                new BitmapImage(new Uri("/ChessOnline;component/Images/white_queen.png", UriKind.Relative)));
            chessImages.Add(ChessOnlineService.ChessType.WhiteKnight,
                new BitmapImage(new Uri("/ChessOnline;component/Images/white_knight.png", UriKind.Relative)));
            chessImages.Add(ChessOnlineService.ChessType.WhiteBishop,
                new BitmapImage(new Uri("/ChessOnline;component/Images/white_bishop.png", UriKind.Relative)));
            chessImages.Add(ChessOnlineService.ChessType.WhiteRook,
                new BitmapImage(new Uri("/ChessOnline;component/Images/white_rook.png", UriKind.Relative)));
            chessImages.Add(ChessOnlineService.ChessType.WhitePawn,
                new BitmapImage(new Uri("/ChessOnline;component/Images/white_pawn.png", UriKind.Relative)));
        }

        public Canvas Canvas
        {
            get { return canvas; }
            set { canvas = value; }
        }
        
        private static Thickness GetChildMargin(Point mouse_pos)
        {
            double center_x = 0;
            double center_y = 0;

            // Находим центр по X
            double iteration = 30;
            double min = 60 + 1;
            for (int i = 0; i < 8; i += 1)
            {
                if (Math.Abs(mouse_pos.X - iteration) < min)
                {
                    min = Math.Abs(mouse_pos.X - iteration);
                    center_x = iteration;
                }
                iteration += 60;
            }

            // Находим центр по Y
            iteration = 30;
            min = 60 + 1;
            for (int i = 0; i < 8; i += 1)
            {
                if (Math.Abs(mouse_pos.Y - iteration) < min)
                {
                    min = Math.Abs(mouse_pos.Y - iteration);
                    center_y = iteration;
                }
                iteration += 60;
            }

            if (center_x == 0 || center_y == 0)
            {
                return new Thickness(0, 0, 0, 0);
            }
            else
            {
                return new Thickness(center_x - 30, center_y - 30, center_x + 30, center_y + 30);
            }
        }

        public void ChessBoardDrawBackground()
        {
            SolidColorBrush black = new SolidColorBrush(Color.FromArgb(255, 0, 202, 225));
            SolidColorBrush white = new SolidColorBrush(Color.FromArgb(255, 192, 247, 253));
            
            for (double x = 30; x < 510; x += 60)
            {
                for (double y = 30; y < 510; y += 60)
                {
                    // Создадим клетку
                    Rectangle rect = new Rectangle();
                    rect.Width = 60;
                    rect.Height = 60;
                    rect.StrokeThickness = 0;
                    rect.Fill = (((x + y) / 60) % 2 == 1 ? white : black);
                    // Получим расположение выделенного квадрата
                    rect.Margin = GetChildMargin(new Point(x, y));
                    rect.Tag = "Cell";
                    // Если полученное расположение выделенного квадрата безошибочно
                    if (!(rect.Margin.Top == 0 && rect.Margin.Bottom == 0))
                    {
                        canvas.Children.Add(rect); // Добавим клетку на доску
                    }
                }
            }
        }

        public void ClearHighlights()
        {
            for (int i = 0; i < canvas.Children.Count; i += 1)
            {
                Rectangle rect = canvas.Children[i] as Rectangle;
                if (rect.Tag.ToString() == "Highlight")
                {
                    canvas.Children.Remove(canvas.Children[i]);
                    i = -1;
                }
            }
        }

        public void SetHighlights(List<ChessOnlineService.Coordinate> coordinates)
        {

            if (coordinates.Count > 0)
            {
                ClearHighlights();

                foreach (var coord in coordinates)
                {
                    Rectangle rect = new Rectangle();
                    rect.Width = 60;
                    rect.Height = 60;
                    rect.StrokeThickness = 3;
                    rect.Tag = "Highlight";
                    rect.Stroke = new SolidColorBrush(Color.FromArgb(255, 0, 255, 0));
                    rect.Fill = new SolidColorBrush(Color.FromArgb(100, 118, 255, 118));
                    //rect.Opacity = 1;
                    // Получим расположение выделенного квадрата
                    rect.Margin = GetChildMarginByBoardCoord(coord);
                    if (!(rect.Margin.Top == 0 && rect.Margin.Bottom == 0))
                    {// Если удалось получить верное расположение
                        canvas.Children.Add(rect); // Добавим квадрат-выделение на доску
                        canvas.Children[canvas.Children.Count - 1].SetValue(Canvas.ZIndexProperty, 200); // чтобы подсветка 
                        //всегда была на первом плане
                    }
                }
            }
        }

        public void UpdatePositions(List<ChessOnlineService.GameCell> list)
        {
            ClearAllFigures();

            // Нарисуем все фигуры заного
            foreach (var cell in list)
            {
                if (cell.FigureType != ChessOnlineService.ChessType.None)
                {// Если на клетке стоит фигура
                    // Отрисуем фигуру
                    Rectangle rect = new Rectangle();
                    rect.Width = 60;
                    rect.Height = 60;
                    rect.StrokeThickness = 0;
                    rect.Tag = "Chess";
                    ImageBrush img = new ImageBrush();
                    img.ImageSource = chessImages[cell.FigureType];
                    img.Stretch = Stretch.Fill;
                    rect.Fill = img;
                    // Получим расположение выделенного квадрата, в который вписана фигура
                    rect.Margin = GetChildMarginByBoardCoord(cell.Coord);
                    if (!(rect.Margin.Top == 0 && rect.Margin.Bottom == 0))
                    {// Если удалось получить верное расположение
                        canvas.Children.Add(rect); // Добавим квадрат-выделение на доску
                    }
                }
            }
        }

        public void ClearAllFigures()
        {
            // Очистим все фигуры с доски
            for (int i = 0; i < canvas.Children.Count; i += 1)
            {
                Rectangle rect = canvas.Children[i] as Rectangle;
                if (rect.Tag.ToString() == "Chess")
                {
                    canvas.Children.Remove(canvas.Children[i]);
                    i -= 1;
                }
            }
        }

        private Thickness GetChildMarginByBoardCoord(ChessOnlineService.Coordinate coord)
        {
            int x = ((int) coord.Literal) * 60 + 30;
            int y = (8 - (int) coord.Number) * 60 + 30;

            return GetChildMargin(new Point(x, y));            
        }

        public static ChessOnlineService.Coordinate GetBoardCoordByMouse(Point mouse_coord)
        {
            ChessOnlineService.Coordinate result = new ChessOnlineService.Coordinate();
            Thickness thick = GetChildMargin(mouse_coord);
            double x_center = thick.Left + 30;
            double y_center = thick.Top + 30;
            result.Literal = (ChessOnlineService.LiteralCoord) ((int)(Math.Round(x_center - 30) / 60));
            result.Number = 8 - ((int)(Math.Round(y_center - 30) / 60));

            return result;
        }

        public bool HasHighlightedCells()
        {
            foreach (var el in canvas.Children)
            {
                if (((string)((Rectangle)el).Tag) == "Highlight")
                {
                    return true;
                }
            }
            return false;
        }
    }
}
